import { tk_bindAccount_main } from "../tk_bindAccount_main.js"
import { openWindowData, closeWindowData } from "../../../api/adsApi/index.js"
import { sendAutomationMessage } from "../../../utils/index.js"
import pLimit from "p-limit"
import { windowIdOfTask } from "../../../config/index.js"
import { puppeteer } from "../../../utils/puppeteer-adapter.js"
import { stopTask } from "../../../utils/index.js"

/**
 * 窗口id绑定业务账号
 * @param {Array} task - 任务数据
 * @param {number} windowIndex - 窗口索引
 * @param {number} headless - 是否无头模式
 * @returns {Promise<Object>} 返回包含执行结果的Promise
 */
export async function tk_bindAccount(task, windowIndex, headless) {
  return new Promise(async (resolve, reject) => {
    console.log("task=====>", task)
    // 获取平台名称
    let platformName = task[0]?.platformName
    // 获取租户id
    let tenantId = task[0]?.tenantId
    // 获取deptId
    let deptId = task[0]?.deptId
    // 获取taskId
    let taskId = task[0]?.taskId
    const bindAccountParams = {
      platformName: platformName,
      tenantId: tenantId,
      deptId: deptId,
      taskId: taskId,
    }
    console.log("bindAccountParams===>", bindAccountParams)
    const startTime = Date.now()
    let successCount = 0
    let failureCount = 0

    const limit = pLimit(1)
    let browser = null
    const failedAccount = []

    // 记录需要关闭的窗口ID
    const openedWindowIds = []

    try {
      // 执行任务 - 为每个子任务添加明确的Promise结构
      const taskPromises = task.map((singleTask, index) => {
        return new Promise(async (resolveTask, rejectTask) => {
          try {
            await limit(async () => {
              const userId = singleTask.deviceId
              console.log(`窗口 ${windowIndex + 1} 开始窗口绑定账号任务 ${singleTask.deviceId}`)

              // 记录窗口ID用于后续关闭
              if (userId) {
                openedWindowIds.push(userId)
              }

              // 使用重试机制打开浏览器
              const openBrowserResponse = await retryOperation(async () => {
                console.log(`尝试连接AdsPower服务，userId: ${userId}, headless: ${headless}`)

                // 检查AdsPower服务是否可用
                try {
                  await new Promise((resolve) => setTimeout(resolve, 1000))
                  // 使用限流控制的函数替代直接调用fetch
                  // const checkResult = await checkBrowserActive(userId);
                  // 不需要再次输出日志，checkBrowserActive已经处理了
                } catch (error) {
                  console.error("AdsPower服务不可用:", error.message)
                  throw new Error(`AdsPower服务不可用: ${error.message}`)
                }

                return await openWindowData({ userId, headless })
              })

              console.log("AdsPower API响应:", JSON.stringify(openBrowserResponse, null, 2))

              // 检查API响应是否成功
              if (!openBrowserResponse || !openBrowserResponse.data || !openBrowserResponse.data.ws) {
                throw new Error(`无法获取浏览器窗口: ${JSON.stringify(openBrowserResponse)}`)
              }

              const wsEndpoint = openBrowserResponse.data.ws.puppeteer
              console.log(`成功获取WebSocket端点: ${wsEndpoint}`)

              // 使用重试机制连接浏览器
              browser = await retryOperation(async () => {
                return await puppeteer.connect({ browserWSEndpoint: wsEndpoint, defaultViewport: null })
              })

              console.log("成功连接到浏览器")

              // 窗口id绑定taskId
              if (!windowIdOfTask[taskId]) {
                windowIdOfTask[taskId] = []
              }
              if (!windowIdOfTask[taskId].find((v) => v == userId)) {
                windowIdOfTask[taskId].push(userId)
                console.log("windowIdOfTask[taskId]==>3", windowIdOfTask[taskId])
              }

              try {
                await tk_bindAccount_main(singleTask, browser, index, taskId, bindAccountParams)
                // 运行绑定任务成功
                successCount++
                resolveTask({
                  success: true,
                  deviceId: userId,
                  message: `账号 ${singleTask.deviceId} 绑定成功`,
                })
              } catch (error) {
                console.error(`窗口 ${windowIndex + 1} 账号 ${singleTask.deviceId} 处理失败:`, error)
                failureCount++
                failedAccount.push(singleTask)
                rejectTask({
                  success: false,
                  deviceId: userId,
                  error: error.message || "绑定账号失败",
                })
              } finally {
                // 无论成功还是失败都尝试关闭浏览器以释放资源
                if (browser) {
                  try {
                    await browser.close()
                    console.log(`窗口 ${windowIndex + 1} 浏览器已关闭`)
                  } catch (closeError) {
                    console.error(`窗口 ${windowIndex + 1} 关闭浏览器时出错:`, closeError)
                  }
                  browser = null
                }
              }
            })
          } catch (error) {
            // 捕获任何在limit执行期间可能发生的错误
            failureCount++
            rejectTask({
              success: false,
              deviceId: singleTask.deviceId,
              error: error.message || "执行绑定账号任务时出错",
            })
          }
        }).catch((error) => {
          // 捕获并记录任务执行错误，但允许其他任务继续
          console.error(`账号 ${error?.deviceId || singleTask?.deviceId || "未知"} 绑定任务异常:`, error)
          return { success: false, error: error.message }
        })
      })

      // 等待所有任务完成，即使某些任务失败也会继续
      const results = await Promise.allSettled(taskPromises)

      console.log(`任务执行结果:`, results.map((r) => r.status).join(", "))

      // 重试失败任务
      if (failedAccount.length > 0) {
        console.log(`窗口 ${windowIndex + 1} 开始重试 ${failedAccount.length} 个失败任务`)

        const retryPromises = failedAccount.map((failedTask, index) => {
          return new Promise(async (resolveRetry, rejectRetry) => {
            try {
              await limit(async () => {
                const userId = failedTask?.deviceId
                // 安全获取标识信息，以防对象结构不完整
                const taskIdentifier = failedTask?.deviceId || (typeof failedTask === "object" ? JSON.stringify(failedTask) : String(failedTask))

                console.log(`重试账号 ${taskIdentifier} 绑定任务`)

                // 使用重试机制打开浏览器
                let localBrowser = null
                try {
                  const openBrowserResponse = await retryOperation(async () => {
                    return await openWindowData({ userId, headless })
                  })

                  if (!openBrowserResponse?.data?.ws) {
                    throw new Error(`重试时无法获取浏览器窗口`)
                  }

                  // 在连接浏览器之前，先检查它是否处于活动状态
                  try {
                    // 使用限流控制的函数替代直接调用fetch
                    // const checkResult = await checkBrowserActive(userId);
                  } catch (error) {
                    console.error("AdsPower服务不可用:", error.message)
                    throw new Error(`AdsPower服务不可用: ${error.message}`)
                  }

                  localBrowser = await puppeteer.connect({
                    browserWSEndpoint: openBrowserResponse.data.ws.puppeteer,
                    defaultViewport: null,
                  })

                  await tk_bindAccount_main(failedTask, localBrowser, index, taskId, bindAccountParams)
                  // 重试成功
                  successCount++
                  resolveRetry({
                    success: true,
                    deviceId: userId,
                    message: `账号 ${taskIdentifier} 重试绑定成功`,
                  })
                } catch (error) {
                  console.error(`重试账号 ${taskIdentifier} 绑定任务仍然失败:`, error)
                  rejectRetry({
                    success: false,
                    deviceId: userId,
                    error: error.message || "重试绑定账号失败",
                  })
                } finally {
                  if (localBrowser) {
                    try {
                      await localBrowser.close()
                    } catch (err) {}
                    localBrowser = null
                  }
                }
              })
            } catch (error) {
              rejectRetry({
                success: false,
                deviceId: failedTask?.deviceId,
                error: error.message || "执行重试绑定账号任务时出错",
              })
            }
          }).catch((error) => {
            // 捕获并记录重试错误，但允许其他重试继续
            const taskId = error?.deviceId || failedTask?.deviceId || "未知"
            console.error(`账号 ${taskId} 重试绑定失败:`, error)
            return { success: false, error: error.message }
          })
        })

        // 等待所有重试完成
        const retryResults = await Promise.allSettled(retryPromises)
        console.log(`重试结果:`, retryResults.map((r) => r.status).join(", "))
      }

      const duration = ((Date.now() - startTime) / 1000).toFixed(2)
      console.log(`窗口 ${windowIndex + 1} 处理完成，总成功: ${successCount}, 总失败: ${failureCount}, 用时: ${duration} 秒`)

      // 处理任务结束，先将成功的结果准备好
      const result = {
        success: true,
        successCount,
        failureCount,
        duration,
        message: `窗口 ${windowIndex + 1} 处理完成，总成功: ${successCount}, 总失败: ${failureCount}, 用时: ${duration} 秒`,
      }

      // 关闭窗口的操作使用setTimeout异步执行，不阻塞当前流程
      setTimeout(async () => {
        try {
          console.log(`[绑定账号] 任务执行完毕，即将关闭所有浏览器窗口`)
          await closeBindAccountWindows(openedWindowIds, taskId)

          // 额外检查是否有遗漏的窗口
          if (windowIdOfTask[taskId] && windowIdOfTask[taskId].length > 0) {
            console.log(`[绑定账号] 发现可能遗漏的窗口，再次关闭: ${windowIdOfTask[taskId].join(", ")}`)
            await closeBindAccountWindows(windowIdOfTask[taskId], taskId)
          }
          console.log(`[绑定账号] 所有浏览器窗口已处理完毕`)
        } catch (error) {
          console.error(`[绑定账号] 延迟关闭窗口时出错:`, error)
        }
      }, 500)

      // 立即resolve，不等待窗口关闭
      console.log("任务执行完成--resolve")
      resolve(result)
    } catch (error) {
      // 开启窗口异常。需要汇报
      console.error(`窗口 ${windowIndex + 1} 异常:`, error)

      // 异步关闭所有浏览器窗口，不阻塞当前流程
      setTimeout(async () => {
        try {
          console.log(`[绑定账号] 错误处理: 关闭所有浏览器窗口`)
          await closeBindAccountWindows(openedWindowIds, taskId)
        } catch (closeError) {
          console.error(`[绑定账号] 错误处理时关闭窗口出错:`, closeError)
        }
      }, 500)

      sendAutomationMessage("send-node-error", `id：${task[0]?.deviceId || "未知"} 窗口异常。请检查窗口id是否正确。`)

      // 任务失败，立即通过reject返回错误，不等待窗口关闭
      reject({
        success: false,
        error: error.message || "绑定账号任务执行失败",
        deviceId: task[0]?.deviceId || "未知",
        successCount,
        failureCount,
      })
    }
  })
}

/**
 * 添加重试函数
 * @param {Function} operation - 要重试的操作函数
 * @param {number} maxRetries - 最大重试次数，默认为3
 * @param {number} delay - 重试间隔，默认为1000毫秒
 * @returns {Promise<any>} - 返回操作结果
 */
async function retryOperation(operation, maxRetries = 3, delay = 1000) {
  let lastError
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await operation()
    } catch (error) {
      lastError = error
      console.error(`操作失败 (尝试 ${i + 1}/${maxRetries}):`, error.message)
      if (i < maxRetries - 1) {
        console.log(`等待 ${delay}ms 后重试...`)
        await new Promise((resolve) => setTimeout(resolve, delay))
      }
    }
  }
  throw lastError
}

/**
 * 关闭绑定账号使用的浏览器窗口
 * @param {Array} deviceIds 设备ID数组
 * @param {string} taskId 任务ID
 */
async function closeBindAccountWindows(deviceIds, taskId) {
  console.log(`[绑定账号] 开始关闭绑定账号的浏览器窗口, 设备数量: ${deviceIds?.length || 0}, 任务ID: ${taskId}`)

  // 跟踪已关闭的窗口ID，避免重复关闭
  const closedWindowIds = new Set()

  try {
    // 1. 首先尝试通过任务ID关闭
    if (taskId && windowIdOfTask[taskId] && windowIdOfTask[taskId].length > 0) {
      console.log(`[绑定账号] 通过任务ID关闭窗口: ${taskId}, 窗口IDs: ${windowIdOfTask[taskId].join(", ")}`)

      try {
        // 使用Promise包装callback以确保异步完成
        await new Promise((resolve) => {
          stopTask(taskId, null, () => {
            console.log(`[绑定账号] 任务 ${taskId} 的所有窗口已关闭`)

            // 将所有关闭的窗口ID添加到跟踪集合
            if (windowIdOfTask[taskId]) {
              windowIdOfTask[taskId].forEach((id) => closedWindowIds.add(id))
            }

            resolve()
          })
        })
      } catch (error) {
        console.error(`[绑定账号] 通过任务ID关闭窗口出错:`, error)
      }
    }

    // 2. 然后使用设备ID逐个关闭窗口，但只关闭尚未关闭的窗口
    if (Array.isArray(deviceIds) && deviceIds.length > 0) {
      // 过滤掉已经关闭的窗口
      const remainingDeviceIds = deviceIds.filter((id) => id && !closedWindowIds.has(id))

      if (remainingDeviceIds.length > 0) {
        console.log(`[绑定账号] 通过设备ID关闭窗口, 剩余IDs: ${remainingDeviceIds.join(", ")}`)

        const closePromises = remainingDeviceIds.map((deviceId) => {
          return new Promise(async (resolve) => {
            try {
              console.log(`[绑定账号] 关闭窗口 ID: ${deviceId}`)
              const response = await closeWindowData({ windowId: deviceId })
              console.log(`[绑定账号] 窗口 ${deviceId} 关闭结果:`, response)

              // 标记窗口为已关闭
              if (response && response.code !== -1) {
                closedWindowIds.add(deviceId)
              }

              resolve(true)
            } catch (error) {
              console.error(`[绑定账号] 关闭窗口 ${deviceId} 出错:`, error)
              resolve(false) // 失败也resolve
            }
          })
        })

        // 并行关闭窗口提高效率，但限制最大并发为3
        for (let i = 0; i < closePromises.length; i += 3) {
          const batch = closePromises.slice(i, i + 3)
          await Promise.all(batch)
          // 短暂等待以避免过快发送请求
          await new Promise((resolve) => setTimeout(resolve, 500))
        }
      } else {
        console.log(`[绑定账号] 所有窗口已在之前的步骤中关闭，无需额外操作`)
      }
    }

    // 清理任务对应的窗口ID记录，只保留未成功关闭的窗口ID
    if (taskId && windowIdOfTask[taskId]) {
      windowIdOfTask[taskId] = windowIdOfTask[taskId].filter((id) => !closedWindowIds.has(id))
      if (windowIdOfTask[taskId].length === 0) {
        console.log(`[绑定账号] 任务 ${taskId} 的所有窗口已成功关闭`)
      } else {
        console.log(`[绑定账号] 任务 ${taskId} 仍有 ${windowIdOfTask[taskId].length} 个窗口未能关闭: ${windowIdOfTask[taskId].join(", ")}`)
      }
    }

    console.log(`[绑定账号] 所有浏览器窗口已处理完毕，共关闭 ${closedWindowIds.size} 个窗口`)
    return true
  } catch (error) {
    console.error(`[绑定账号] 关闭窗口过程中发生错误:`, error)
    console.log(`[绑定账号] 所有浏览器窗口已处理完毕`)
    return false
  }
}